如果我們的Excel有一些敏感資料,那在文件匯出時加密是很重要的,Apache POI也有提供加密與讀取時解密的功能。
這篇同樣以學生成績資料表來作為實作範例。
加密的步驟必須放在當我們將資料寫入Workbook之後,準備匯出Excel之前,拿文件的資料流ByteArrayOutputStream去進行加密。
// 略...
// 寫入ByteArrayOutputStream 匯出Excel
workbook.write(bos);
// 加密
ByteArrayResource resource = new ByteArrayResource(this.setEncrypt(bos));
return resource.getByteArray();
加密的步驟如下:
EncryptionMode.standard
。不過我還沒有研究這些模式分別是用什麼標準或演算法,可以參考官方文件:Apache POI™ - Encryption supportprivate byte[] setEncrypt(ByteArrayOutputStream bos) throws IOException, InvalidFormatException, GeneralSecurityException {
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
Encryptor encryptor = info.getEncryptor();
// 設定加密密碼
encryptor.confirmPassword("password");
// 打開文件
OPCPackage opc = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()));
OutputStream os = encryptor.getDataStream(fs);
// 儲存加密內容
opc.save(os);
opc.close();
// 匯出前一定要先關閉加密文件OutputStream,不然會顯示匯出的文件損壞
os.close();
// 再將已加密的資料寫入ByteArrayOutputStream
ByteArrayOutputStream encryptedStream = new ByteArrayOutputStream();
fs.writeFilesystem(encryptedStream);
encryptedStream.close();
return encryptedStream.toByteArray();
}
成功加密之後,打開文件查看內容之前,就會被要求要先輸入密碼囉
如果用程式讀取被加密的文件,沒有解密的話會出現Exception:
想解密檔案的話可以在取得檔案FileInputStream之後進行。
public void readExcel(String filePath) {
// 欄位名稱
String[] columnNames = {"學號", "科系", "年級", "姓名", "課程", "成績", "考試日期"};
List<StudentCourseScoreReportModel> modelList = new ArrayList<>();
try {
FileInputStream fileInputStream = new FileInputStream(Paths.get(filePath).toFile());
// 解密
Workbook workbook = this.decryptExcel(fileInputStream, "password");
// 以下略...
getDataStream()
能取得解密後的InputStreamprivate Workbook decryptExcel(FileInputStream fileInputStream, String password) throws IOException, GeneralSecurityException {
POIFSFileSystem fs = new POIFSFileSystem(fileInputStream);
EncryptionInfo encInfo = new EncryptionInfo(fs);
Decryptor decryptor = Decryptor.getInstance(encInfo);
decryptor.verifyPassword(password);
Workbook workbook = new XSSFWorkbook(decryptor.getDataStream(fs));
return workbook;
}
解密成功後,就能順利讀取Excel拿到資料了。